<template>
  <el-container>
    <el-aside width="200px">
      <el-tree :data="treeData" default-expand-all @current-change="treeCurrentChange"
        :props="{ class: customNodeClass }" />
    </el-aside>
    <el-container>
      <el-main>
        <RelationGraph ref="graphRef$" :options="options" @contextmenu="handleRightClick" @node-click="handleNodeClick">
          <template #node="{ node }">
            <div v-if="node.type == 'diamond'" class="graph-node-container my-rg-node my-cool-node-diamond"
              :data-node="JSON.stringify({ id: node.id, data: node.data, text: node.text, type: 'diamond' })">
              {{ node.text }}
            </div>
            <div v-else :style="getNodeInlineStyle(node.id)" class="graph-node-container" :data-id="node.id"
              :class="node.nodeShape == 1 ? 'is-nodeShape' : ''"
              :data-node="JSON.stringify({ id: node.id, data: node.data, text: node.text })">
              <!-- 四向拉伸手柄（放在容器内侧，不越界） -->
              <div class="resize-handle handle-top" @mousedown.stop="beginResize(node.id, 'top', $event)"></div>
              <div class="resize-handle handle-right" @mousedown.stop="beginResize(node.id, 'right', $event)"></div>
              <div class="resize-handle handle-bottom" @mousedown.stop="beginResize(node.id, 'bottom', $event)"></div>
              <div class="resize-handle handle-left" @mousedown.stop="beginResize(node.id, 'left', $event)"></div>

              <!-- 内层包裹：不再位移，避免与外层 transform 叠加 -->
              <div class="graph-node-inner" v-if="node.data.type == 1">
                <div v-if="!editingNodeId || editingNodeId !== node.id">
                  {{ node.text }}
                </div>
                <el-input v-else v-model="editingNodeText" class="node-edit-input" @blur="confirmRename(node.id)"
                  @keyup.enter="confirmRename(node.id)" @keyup.esc="cancelRename" ref="editInputRef" />
                <table class="c-data-table">
                  <tr>
                    <th>名称</th>
                    <th>类型</th>
                  </tr>
                  <template v-for="column of node.data.columns" :key="column.name">
                    <tr>
                      <td>
                        <div :id="`${node.id}-${column.name}`">{{ column.name }}</div>
                      </td>
                      <td>{{ column.type }}</td>
                    </tr>
                  </template>
                </table>
              </div>
              <div v-if="node.data.type == 3">
                {{ node.text }}
              </div>
            </div>
          </template>
        </RelationGraph>

        <!-- 1. 节点右键菜单 -->
        <div v-show="showNodeContextMenu" :style="nodeContextMenuStyle" class="context-menu" @click.stop>
          <div class="menu-item" v-if="d == 1" @click="handleDesignTable">设计表</div>
          <div class="menu-item" v-if="d == 3" @click="handleRelationship">添加关系</div>
          <div class="menu-item" @click="handleRenameNode">重命名</div>
          <div class="menu-item" @click="handleDeleteNode" style="color: #ff4d4f;">删除表</div>
        </div>

        <!-- 2. 空白处右键菜单 -->
        <div v-show="showBlankContextMenu" :style="blankContextMenuStyle" class="context-menu" @click.stop>
          <div class="menu-item" @click="addNode">{{ d == 3 ? '添加实体 ' : '添加节点' }}</div>
          <div class="menu-item" @click="clearGraph" v-if="isClear">清空图表</div>
        </div>
      </el-main>
      <el-footer>
        <el-button type="primary" @click="saveClick">保存</el-button>
      </el-footer>
    </el-container>
  </el-container>

  <DesignTableDialog :visible="showDesignDialog" :tableName="tableName" @cancel="cancel"
    @saveTableDesign="saveTableDesign" />
  <RelationshipDialog :visible="visibleRelationship" :id="relationshipInfo.id" @cancel="cancelRelationshipDialog"
    @save="saveRelationshipDialog" />
</template>

<script setup lang="ts">
import { onMounted, ref, nextTick, computed } from 'vue'
import RelationGraph from 'relation-graph-vue3'
import type { RelationGraphComponent, RGJsonData, RGNode } from 'relation-graph-vue3'
import { ElMessageBox, ElMessage } from 'element-plus'
import DesignTableDialog from '@/components/designTableDialog.vue'
import RelationshipDialog from '@/components/relationship.vue'

import { useApp } from '@/store/app.ts'
import { useForeignKey } from '@/store/foreignKey.ts'
const useForeignKeyStore = useForeignKey()
import { useField } from '@/store/field.ts'
const useFieldStore = useField()
import { storeToRefs } from 'pinia'
const useAppStore = useApp()
const { treeData, lines, count } = storeToRefs(useAppStore)

const graphRef$ = ref<RelationGraphComponent | null>(null)
const graphData = ref<RGJsonData>({
  rootId: 'root',
  nodes: [],
  lines: []
})

// 限制数值在 [min, max] 范围
function clamp(v: number, min: number, max: number): number {
  return Math.min(Math.max(v, min), max)
}

// 刷新图（仅在必要时调用）
const refreshGraph = () => {
  const ls = graphData.value.lines
  useAppStore.setLines(ls)
  graphRef$.value?.setJsonData(graphData.value)
}

const options = {
  defaultExpandHolderPosition: 'right',
  allowNodeDrag: true,
  allowShowDownloadButton: false,
  layout: { layoutName: 'fixed' }
}

// 右键菜单
const showNodeContextMenu = ref(false)
const showBlankContextMenu = ref(false)
const nodeContextMenuStyle = ref({ left: '0px', top: '0px', position: 'fixed', zIndex: 1000 })
const blankContextMenuStyle = ref({ left: '0px', top: '0px', position: 'fixed', zIndex: 1000 })
const currentNode = ref<RGNode | null>(null)
const setContextMenuPosition = (styleRef: { value: any }, event: MouseEvent) => {
  styleRef.value = { ...styleRef.value, left: `${event.clientX}px`, top: `${event.clientY}px` }
}
const d = ref(3)
// 节点尺寸管理
const DEFAULT_NODE_WIDTH = d.value == 3 ? 200 : 150
const DEFAULT_NODE_HEIGHT = d.value == 3 ? 100 : 200
type NodeSize = { width: number; height: number }
const nodeSizes = ref<Record<string, NodeSize>>({})

const getNodeSize = (nodeId: string) => {
  return nodeSizes.value[nodeId] || { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT }
}

const setNodeSize = (nodeId: string, width: number, height: number) => {
  const minWidth = 100,
    minHeight = 80,
    maxWidth = 600,
    maxHeight = 500
  nodeSizes.value[nodeId] = {
    width: Math.min(Math.max(width, minWidth), maxWidth),
    height: Math.min(Math.max(height, minHeight), maxHeight)
  }
}

// 容器仅负责尺寸
const getNodeInlineStyle = (nodeId: string, type: string | number = 1) => {
  const size = getNodeSize(nodeId)
  if (type == 3) {
    return {
      width: `${size.width}px`,
      height: `${size.height}px`,
      backgroundColor: 'rgba(55,131,192)',
      position: 'relative',
      boxSizing: 'border-box'
    }
  }
  return {
    width: `${size.width}px`,
    height: `${size.height}px`,
    backgroundColor: '#3783c0',
    position: 'relative',
    boxSizing: 'border-box'
  } as any
}

// 拖拽状态
type ResizeEdge = 'top' | 'right' | 'bottom' | 'left'
const resizing = ref<null | {
  nodeId: string
  edge: ResizeEdge
  startX: number
  startY: number
  startWidth: number
  startHeight: number
  nodeStartX: number
  nodeStartY: number
  outerEl: HTMLElement | null
  baseTransform: string
}>(null)

// 查找 RelationGraph 外层节点容器（包含高亮环的那个）
function findOuterNodeEl(container: HTMLElement | null): HTMLElement | null {
  if (!container) return null
  let el: HTMLElement | null = container
  while (el && el !== document.body) {
    if (el.classList.contains('rel-node')) return el
    el = el.parentElement as HTMLElement | null
  }
  // 兜底：模糊匹配包含 rel-node 文本的类名
  return (container.closest('[class*="rel-node"]') as HTMLElement) || null
}

const onResizingMouseMove = (e: MouseEvent) => {
  const st = resizing.value
  if (!st) return
  const { nodeId, edge, startX, startY, startWidth, startHeight, outerEl, baseTransform } = st

  const dx = e.clientX - startX
  const dy = e.clientY - startY
  const minW = 100,
    maxW = 600
  const minH = 80,
    maxH = 500

  if (!outerEl) return

  if (edge === 'right') {
    const newW = clamp(startWidth + dx, minW, maxW)
    setNodeSize(nodeId, newW, startHeight)

    // 同步外层尺寸（不位移）
    outerEl.style.width = newW + 'px'
    outerEl.style.height = startHeight + 'px'
    outerEl.style.transform = baseTransform
    return
  }

  if (edge === 'bottom') {
    const newH = clamp(startHeight + dy, minH, maxH)
    setNodeSize(nodeId, startWidth, newH)

    outerEl.style.width = startWidth + 'px'
    outerEl.style.height = newH + 'px'
    outerEl.style.transform = baseTransform
    return
  }

  if (edge === 'left') {
    let tentativeW = clamp(startWidth - dx, minW, maxW)
    const appliedDx = startWidth - tentativeW // 固定右边需要右移的量
    setNodeSize(nodeId, tentativeW, startHeight)

    outerEl.style.width = tentativeW + 'px'
    outerEl.style.height = startHeight + 'px'
    outerEl.style.transform = `${baseTransform} translate(${appliedDx}px, 0)`
    return
  }

  if (edge === 'top') {
    let tentativeH = clamp(startHeight - dy, minH, maxH)
    const appliedDy = startHeight - tentativeH // 固定下边需要下移的量
    setNodeSize(nodeId, startWidth, tentativeH)

    outerEl.style.width = startWidth + 'px'
    outerEl.style.height = tentativeH + 'px'
    outerEl.style.transform = `${baseTransform} translate(0, ${appliedDy}px)`
    return
  }
}

const onResizingMouseUp = () => {
  const st = resizing.value
  if (!st) return
  const { nodeId, nodeStartX, nodeStartY, edge, startWidth, startHeight, outerEl } = st

  let dxCommit = 0,
    dyCommit = 0
  const size = getNodeSize(nodeId)
  if (edge === 'left') dxCommit = startWidth - size.width
  if (edge === 'top') dyCommit = startHeight - size.height

  // 提交坐标（沉淀临时位移）
  const idx = graphData.value.nodes.findIndex(n => n.id === nodeId)
  if (idx > -1) {
    graphData.value.nodes[idx].x = nodeStartX + dxCommit
    graphData.value.nodes[idx].y = nodeStartY + dyCommit
  }

  // 清理外层临时 transform（回归数据驱动）
  if (outerEl) {
    outerEl.style.transform = ''
  }

  refreshGraph()

  document.removeEventListener('mousemove', onResizingMouseMove)
  document.removeEventListener('mouseup', onResizingMouseUp)
  resizing.value = null
}

const beginResize = (nodeId: string, edge: ResizeEdge, e: MouseEvent) => {
  e.preventDefault()
  e.stopPropagation()

  const size = getNodeSize(nodeId)
  const node = graphData.value.nodes.find(n => n.id === nodeId)!

  const container = (e.currentTarget as HTMLElement).closest('.graph-node-container') as HTMLElement | null
  const outerEl = findOuterNodeEl(container)
  let baseTransform = ''
  if (outerEl) {
    const cs = getComputedStyle(outerEl)
    baseTransform = cs.transform === 'none' ? '' : cs.transform
    // 初次记录时，确保外层尺寸与内部容器一致
    outerEl.style.width = size.width + 'px'
    outerEl.style.height = size.height + 'px'
  }

  resizing.value = {
    nodeId,
    edge,
    startX: e.clientX,
    startY: e.clientY,
    startWidth: size.width,
    startHeight: size.height,
    nodeStartX: node.x ?? 0,
    nodeStartY: node.y ?? 0,
    outerEl,
    baseTransform
  }

  document.addEventListener('mousemove', onResizingMouseMove)
  document.addEventListener('mouseup', onResizingMouseUp)
}

// 重命名/表设计等逻辑
const editingNodeId = ref<string | null>(null)
const editingNodeText = ref('')
const editInputRef = ref<HTMLInputElement | null>(null)

const showDesignDialog = ref(false)
const tableName = ref('')

const isClear = computed(() => graphData.value.nodes.length > 0)

onMounted(() => {
  if (treeData.value[0].children && treeData.value[0].children.length > 0) {
    graphData.value.nodes = treeData.value[0].children.map((it: any) => it.otherData)
    if (lines.value.length > 0) {
      graphData.value.lines = lines.value
    }
  }
  refreshGraph()
})

const handleRightClick = (event: MouseEvent, node?: RGNode) => {
  event.preventDefault()
  event.stopPropagation()
  closeAllContextMenu()

  const isClickNode =
    event.target instanceof HTMLElement && (event.target.closest('.graph-node-container') as HTMLElement | null)

  if (isClickNode) {
    try {
      const dataAttr = (isClickNode as HTMLElement).getAttribute('data-node')
      currentNode.value = dataAttr ? JSON.parse(dataAttr) : node || null
    } catch (_) {
      currentNode.value = node || null
    }
    if (currentNode.value) {
      showNodeContextMenu.value = true
      setContextMenuPosition(nodeContextMenuStyle as any, event)
    } else {
      showBlankContextMenu.value = true
      setContextMenuPosition(blankContextMenuStyle as any, event)
    }
  } else {
    showBlankContextMenu.value = true
    setContextMenuPosition(blankContextMenuStyle as any, event)
  }

  const closeMenu = () => {
    closeAllContextMenu()
    document.removeEventListener('click', closeMenu)
  }
  setTimeout(() => document.addEventListener('click', closeMenu), 0)
}

const treeCurrentChange = (node: any) => {
  useAppStore.setNodeShape(node.id)
  if (treeData.value[0].children && treeData.value[0].children.length > 0) {
    graphData.value.nodes = treeData.value[0].children.map((it: any) => it.otherData)
    if (lines.value.length > 0) {
      graphData.value.lines = lines.value
    }
  }
  refreshGraph()
}

const handleNodeClick = (node: RGNode) => {
  treeCurrentChange(node)
}

const customNodeClass = (node: any) => (node?.otherData?.nodeShape == 1 ? 'is-nodeShape' : null)

const closeAllContextMenu = () => {
  showNodeContextMenu.value = false
  showBlankContextMenu.value = false
}

const saveClick = () => {
  console.log('saveClick', graphData.value)
}

const addNode = () => {
  if (!graphRef$.value) return
  const newNodeId = `node_${Date.now()}`
  const left = parseInt(blankContextMenuStyle.value.left) || 0
  const top = parseInt(blankContextMenuStyle.value.top) || 0
  const temp = {
    id: newNodeId,
    text: `table_${count.value}`,
    x: left + 20,
    y: top + 20,
    color: '#3783c0',
    data: { columns: [], foreignKey: [] }
  }
  graphData.value.nodes.push({ ...temp, nodeShape: 1 })
  useAppStore.add({ label: temp.text, id: temp.id, otherData: { ...temp, nodeShape: 1 } })
  useAppStore.setCount()
  refreshGraph()
  closeAllContextMenu()
}

const clearGraph = () => {
  if (!graphRef$.value || !confirm('确定要清空图表吗？')) return
  graphData.value.nodes = []
  graphData.value.lines = []
  refreshGraph()
  useAppStore.clear()
  closeAllContextMenu()
}

const handleDesignTable = () => {
  if (!currentNode.value) return
  const node = currentNode.value
  tableName.value = node.text!
  useFieldStore.setData(node.data!.columns.length ? node.data!.columns : [])
  useForeignKeyStore.setData(node.data!.foreignKey.length ? node.data!.foreignKey : [])
  showDesignDialog.value = true
  closeAllContextMenu()
}
const visibleRelationship = ref(true)
const relationshipInfo = ref({ id: '' })
const handleRelationship = () => {
  if (!currentNode.value) return
  const node = currentNode.value
  relationshipInfo.value.id = node.id
  visibleRelationship.value = true
}

const cancelRelationshipDialog = () => {
  visibleRelationship.value = false
}
const saveRelationshipDialog = (data: any[]) => {
  if (!currentNode.value) return;
  const sourceNodeId = currentNode.value.id; // 源节点ID（触发添加关系的节点）
  const sourceNodeIndex = graphData.value.nodes.findIndex(n => n.id === sourceNodeId);
  
  // 1. 校验源节点是否存在（防御性判断）
  if (sourceNodeIndex === -1) {
    ElMessage.error('源节点不存在，无法添加关系');
    return;
  }
  const sourceNode = graphData.value.nodes[sourceNodeIndex];

  // 2. 清理源节点已有的旧关系（避免重复）
  // 2.1 提取源节点旧关系的菱形节点ID（从节点data中获取）
  const oldRelationshipNodeIds = sourceNode.data?.relationships 
    ? sourceNode.data.relationships.map((rel: any) => rel.diamondNodeId) 
    : [];
  
  // 2.2 删除旧关系的菱形节点
  graphData.value.nodes = graphData.value.nodes.filter(n => 
    !oldRelationshipNodeIds.includes(n.id)
  );
  
  // 2.3 删除旧关系的连接线（与源节点/旧菱形节点相关的线）
  graphData.value.lines = graphData.value.lines.filter(line => 
    line.from !== sourceNodeId && 
    line.to !== sourceNodeId && 
    !oldRelationshipNodeIds.some((oldId: string) => line.from === oldId || line.to === oldId)
  );

  // 3. 处理新关系数据，生成菱形节点和连接线
  const newRelationships: any[] = []; // 存储新关系（用于同步到节点data和Store）
  
  data.forEach((relation: any) => {
    // 3.1 校验目标节点是否存在（防止无效关系）
    const targetNodeExists = graphData.value.nodes.some(n => n.id === relation.correlation);
    if (!targetNodeExists) {
      ElMessage.warning(`目标节点【${relation.correlation}】不存在，跳过该关系`);
      return;
    }

    // 3.2 生成唯一ID（规则：源节点ID_目标节点ID_时间戳，避免冲突）
    const timestamp = Date.now();
    const diamondNodeId = `rel_diamond_${sourceNodeId}_${relation.correlation}_${timestamp}`; // 菱形节点ID
    const lineIdFromSourceToDiamond = `rel_line_${sourceNodeId}_to_${diamondNodeId}`; // 源节点→菱形线ID
    const lineIdFromDiamondToTarget = `rel_line_${diamondNodeId}_to_${relation.correlation}`; // 菱形→目标节点线ID

    // 3.3 添加菱形节点（关系中间节点）
    const diamondNode = {
      id: diamondNodeId,
      text: `${relation.cardinal}:${relation.sideCardinal}`, // 关系文本（如 1:N）
      type: 'diamond',
      color: 'transparent',
      // 菱形节点位置：源节点与目标节点中间（优化布局）
      x: (sourceNode.x || 0) + (graphData.value.nodes.find(n => n.id === relation.correlation)?.x || 0 - (sourceNode.x || 0)) / 2,
      y: (sourceNode.y || 0) + (graphData.value.nodes.find(n => n.id === relation.correlation)?.y || 0 - (sourceNode.y || 0)) / 2,
      data: {
        sourceNodeId: sourceNodeId,       // 关联源节点ID
        targetNodeId: relation.correlation, // 关联目标节点ID
        cardinal: relation.cardinal,     // 源→目标基数（如 1）
        sideCardinal: relation.sideCardinal // 目标→源基数（如 N）
      }
    };
    graphData.value.nodes.push(diamondNode);

    // 3.4 添加源节点→菱形节点的连接线
    graphData.value.lines.push({
      id: lineIdFromSourceToDiamond, // 线唯一ID（便于后续删除）
      text: relation.cardinal,       // 线文本（基数）
      from: sourceNodeId,
      to: diamondNodeId,
      lineShape: 3,
      lineWidth: 3,
      color: 'rgb(255,120,0,1)',
      fontColor: 'rgb(255,255,255,1)'
    });

    // 3.5 添加菱形节点→目标节点的连接线
    graphData.value.lines.push({
      id: lineIdFromDiamondToTarget, // 线唯一ID
      text: relation.sideCardinal,   // 线文本（反向基数）
      from: diamondNodeId,
      to: relation.correlation,
      lineShape: 3,
      lineWidth: 3,
      color: 'rgb(255,120,0,1)',
      fontColor: 'rgb(255,255,255,1)'
    });

    // 3.6 记录新关系（用于存入源节点data）
    newRelationships.push({
      diamondNodeId: diamondNodeId,
      targetNodeId: relation.correlation,
      cardinal: relation.cardinal,
      sideCardinal: relation.sideCardinal,
      lines: [lineIdFromSourceToDiamond, lineIdFromDiamondToTarget] // 关联的线ID
    });
  });

  // 4. 将新关系存入源节点的data字段（数据绑定，参考saveTableDesign）
  sourceNode.data = {
    ...sourceNode.data,
    relationships: newRelationships // 覆盖旧关系，存储新关系
  };
  graphData.value.nodes[sourceNodeIndex] = sourceNode; // 更新源节点

  // 5. 同步关系数据到Pinia Store（确保全局状态一致，参考saveTableDesign）
  useAppStore.setOtherData(sourceNodeId, {
    ...sourceNode.data, // 保留原有data（如columns/foreignKey）
    relationships: newRelationships
  });

  // 6. 刷新图表，关闭对话框
  refreshGraph();
  visibleRelationship.value = false;
  ElMessage.success(`成功添加${newRelationships.length}个关系`);
};
// const saveRelationshipDialog = (data: any[]) => {
//   if (!currentNode.value) return
//   const nodeId = currentNode.value!.id
//   data.forEach((it: any) => {
//     const temp = {
//       id: `${nodeId}-${it.id}`,
//       text: `${it.cardinal}:${it.sideCardinal}`,
//       type: 'diamond',
//       color: 'transparent'
//       , data: {
//         ...it
//       }
//     }
//     graphData.value.nodes.push({
//       ...temp
//     })
//     graphData.value.lines.push({
//       text: it.cardinal,
//       from: nodeId,
//       to: `${nodeId}-${it.id}`
//       , lineShape: 3,
//       lineWidth: 3,
//       color: 'rgb(255,120,0,1)',
//       fontColor: 'rgb(255,255,255,1)'
//     })
//     graphData.value.lines.push({
//       text: it.cardinal,
//       from: `${nodeId}-${it.id}`,
//       to: it.correlation,
//       lineShape: 3,
//       lineWidth: 3,
//       color: 'rgb(255,120,0,1)',
//       fontColor: 'rgb(255,255,255,1)'
//     })
//   })
//   refreshGraph()
// }

const handleRenameNode = () => {
  if (!currentNode.value) return
  const node = currentNode.value
  editingNodeId.value = node.id
  editingNodeText.value = node.text!
  nextTick(() => editInputRef.value?.focus())
  closeAllContextMenu()
}

const confirmRename = (nodeId: string) => {
  const nodeIndex = graphData.value.nodes.findIndex(n => n.id === nodeId)
  if (nodeIndex > -1 && editingNodeText.value.trim()) {
    graphData.value.nodes[nodeIndex].text = editingNodeText.value.trim()
    refreshGraph()
  }
  useAppStore.editName(nodeId, editingNodeText.value.trim())
  editingNodeId.value = null
}

const cancelRename = () => {
  editingNodeId.value = null
}

const handleDeleteNode = () => {
  ElMessageBox.confirm('确定要删除吗', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
    .then(() => {
      const nodeId = currentNode.value!.id
      graphData.value.nodes = graphData.value.nodes.filter(n => n.id !== nodeId)
      graphData.value.lines = graphData.value.lines.filter(line => line.from !== nodeId && line.to !== nodeId)
      refreshGraph()
      useAppStore.del(nodeId)
      closeAllContextMenu()
      currentNode.value = null
    })
    .catch(() => {
      ElMessage.info('你取消了删除')
    })
}

const cancel = () => {
  showDesignDialog.value = false
  useForeignKeyStore.clear()
  useFieldStore.clear()
}

const saveTableDesign = ({ field, foreignKey }: { field: any[]; foreignKey: any[] }) => {
  const nodeId = currentNode.value!.id
  const nodeIndex = graphData.value.nodes.findIndex(n => n.id === nodeId)
  if (nodeIndex > -1) {
    graphData.value.nodes[nodeIndex].data!.foreignKey = foreignKey
    graphData.value.nodes[nodeIndex].data!.columns = field
    graphData.value.lines = graphData.value.lines.filter(line => line.from !== nodeId)
    const uniqueFathers = Array.from(
      new Set(foreignKey.map((fk: any) => fk.fatherTable).filter((father: string) => father && father !== nodeId))
    )
    uniqueFathers.forEach((fatherTable: string) => {
      graphData.value.lines.push({ from: nodeId, to: fatherTable, lineShape: 5, color: '#ffd700' })
    })
    refreshGraph()
  }
  useAppStore.setOtherData(nodeId, { field, foreignKey })
  cancel()
}
</script>

<style lang="scss" scoped>
.my-rg-node {
  display: flex;
  place-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
  box-sizing: border-box;
}

.el-container {
  height: 100%;
}

:deep(.el-tree) {
  .is-nodeShape {
    background-color: #f00;
  }
}

.el-footer {
  display: flex;
  justify-content: flex-end;
}

/* 关系图基础样式 */
::v-deep(.relation-graph) {
  .rel-node-checked {
    box-shadow: none;
  }

  .my-cool-node-diamond {
    width: 100%;
    height: 100%;
    clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    background-color: rgba(55, 131, 192);
  }

  .graph-node-container {
    overflow: hidden;
  }

  .is-nodeShape {
    box-shadow: 0 0 0 8px #ff00004d;
  }

  .rel-map {
    background-color: rgba(255, 0, 0, 0.1);
    background-size: 30px 30px;
    background-image: linear-gradient(90deg, rgba(0, 0, 0, 0.1) 1px, transparent 0),
      linear-gradient(180deg, rgba(0, 0, 0, 0.1) 1px, transparent 0);
  }
}

.el-main {
  padding: 0;
}

/* 右键菜单 */
.context-menu {
  width: 120px;
  background: white;
  border-radius: 4px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  border: 1px solid #e0e0e0;
  padding: 5px 0;

  .menu-item {
    padding: 8px 15px;
    font-size: 14px;
    cursor: pointer;
    transition: background 0.2s;

    &:hover {
      background-color: #f5f5f5;
      color: #1890ff;
    }
  }
}

/* 节点表格样式 */
.c-data-table {
  background-color: #ffffff;
  border-collapse: collapse;
  width: 100%;
  margin-top: 10px;

  td,
  th {
    border: 1px solid #3783c0;
    color: #333333;
    padding: 5px;
    text-align: center;
  }

  td div {
    background-color: #1da9f5;
    color: #ffffff;
    border-radius: 5px;
    padding: 2px 0;
  }
}

/* 节点重命名输入框样式 */
.node-edit-input {
  width: 100%;
  padding: 4px 8px;
  border: 1px solid #1da9f5;
  border-radius: 4px;
  outline: none;
  font-size: 14px;
}

/* 节点容器与内层 */
.graph-node-container {
  overflow: hidden;
  position: relative;
  box-sizing: border-box;
}

.graph-node-inner {
  position: absolute;
  inset: 0;
}

/* 拉伸手柄样式（贴内缘，不越界） */
.resize-handle {
  position: absolute;
  background: transparent;
  z-index: 2;
}

.handle-top {
  top: 0;
  left: 0;
  right: 0;
  height: 6px;
  cursor: ns-resize;
}

.handle-right {
  top: 0;
  right: 0;
  width: 6px;
  bottom: 0;
  cursor: ew-resize;
}

.handle-bottom {
  bottom: 0;
  left: 0;
  right: 0;
  height: 6px;
  cursor: ns-resize;
}

.handle-left {
  top: 0;
  left: 0;
  width: 6px;
  bottom: 0;
  cursor: ew-resize;
}
</style>